#ifndef __BUFFER_H__
#define __BUFFER_H__

#include <algorithm>
#include <vector>
#include <cassert>

// 异步日志器缓冲区(直接存放格式化后的日志信息字符串)
// 1. 减少LogMessage构造消耗
// 2. 针对日志信息一次性IO操作

namespace log_system
{
#define DEFAULT_BUFFER_SIZE (1 * 1024 * 1024) // 1M
#define THRESHOLD_VALUE (8 * 1024 * 1024)     // 8M(阈值)
#define INCREMENT (1 * 1024 * 1024)           // 1M(增量)

    class Buffer
    {
    public:
        Buffer()
            : _buffer(DEFAULT_BUFFER_SIZE), _writeable_index(0), _readable_index(0) {}

    public:
        void write(const char *data, size_t length) // 写入缓冲区
        {
            // 缓冲区剩余空间不足 -> 1. 扩容 2. 限制返回
            // // 固定大小直接返回
            // if (length > writeableLength())
            //     return;

            // 动态扩容
            reserve(length);
            std::copy(data, data + length, &_buffer[_writeable_index]);
            offsetWritePointer(length);
        }

        const char *readableBeginPointer() // 返回可读数据起始地址
        {
            return &_buffer[_readable_index];
        }

        size_t readableLength() // 可读数据长度
        {
            return (_writeable_index - _readable_index);
        }

        size_t writeableLength() // 可写数据长度(固定大小缓冲区)、
        {
            // std::cout << "buffer size : " << _buffer.size() << std::endl;
            return (_buffer.size() - _writeable_index);
        }

        void offsetReadPonter(size_t length) // 偏移读取地址
        {
            assert(length <= readableLength());
            _readable_index += length;
        }

        void swap(Buffer& buffer) // 缓冲区交换
        {
            _buffer.swap(buffer._buffer);
            std::swap(_readable_index, buffer._readable_index);
            std::swap(_writeable_index, buffer._writeable_index);
        }

        bool empty() // 判断缓冲区是否为空
        {
            return (_readable_index == _writeable_index);            
        }

        void reset() // 重置读写地址
        {
            _writeable_index = _readable_index = 0;
        }

    private:
        void reserve(size_t length) // 扩容
        {
            if (length <= writeableLength())
                return;
            size_t new_size = 0;
            if (_buffer.size() < THRESHOLD_VALUE) // 小于阈值翻倍增长
            {
                new_size = _buffer.size() * 2 + length;
            }
            else // 大于阈值线性增长
            {
                new_size = _buffer.size() + INCREMENT + length;
            }
            _buffer.resize(new_size);
        }

        void offsetWritePointer(size_t length) // 偏移写入地址
        {
            assert((length + _writeable_index) <= _buffer.size());
            _writeable_index += length;
        }

    private:
        std::vector<char> _buffer;
        size_t _readable_index;  // 可读下标
        size_t _writeable_index; // 可写下标
    };

} // namespace log_system

#endif // #ifndef __BUFFER_H__
